<?php

namespace catchAdmin\visitPlan\model;

use app\common\lib\ZhyxBeanstalkd;
use app\common\lib\ZhyxMongo;
use app\common\model\BaseModel;
use app\common\model\CollectClass;
use app\common\model\DiseasePatientTaskDetail;
use app\common\model\PatientInfo;
use app\common\model\TimingTask;
use catchAdmin\apidoctor\controller\Patient;
use catchAdmin\visitPlan\search\VisitPlanSearch;
use catcher\exceptions\FailedException;
use MongoDB\BSON\ObjectId;


class VisitPlan extends BaseModel
{
    use VisitPlanSearch;

    public $name = 'visit_plan';

    public function createData(array $data): bool
    {
        $weekValue = ["1" => "1 week", "2" => "2 week", "3" => "1 month", "4" => "3 month", "5" => "6 month", "6" => "1 year"];
        $patientSearch = $data["group_id"] ?? "";
        if (!empty($patientSearch) && $data["is_all"] === true) {
            $data["patientIds"] = (new PatientInfo())->getAllPatientIds($data["group_id"], $data["creator_id"], 'patientId', 1, true);
            if (empty($data["patientIds"])) {
                throw new FailedException("患者不存在");
            }
        }
        $patientList = (new PatientInfo())->getPatientListByUid($data["patientIds"], ["presentTelphone", "patientId", "sex", "inage", "name", "inList.outhospitalDeptCode", "inList.outhospitalDate", "inList.diagnose"]);

        if (empty($patientList)) {
            throw new FailedException("患者不存在");
        }
        $connection = ZhyxMongo::getInstance()->connection;
        $session = $connection->startSession();

        try {
            $data["receiv_count"] = count($patientList);
            $data["deleted_at"] = 0;
            $data["status"] = 0;
            $data["push_date"] = "";
            $delay = 0;
            $session->startTransaction(['session' => $session]);

            $result = ZhyxMongo::getInstance()->setCollection("visit_plan")->insertOne($data, ['session' => $session]);
            if ($result->getInsertedId()) {
                //根据data下的患者id数组获取患者list
                $pushArr = ["visit_id" => (string)$result->getInsertedId(), 'task_name' => $data["visit_name"], 'tubeName' => "sendVisitMessage"];
                $arr = [];

                foreach ($patientList as $k => $v) {
                    $arr[] = [
                        'visit_id' => (string)$result->getInsertedId(),
                        'patientName' => $v['name'],
                        'sex' => $v['sex'],
                        'inage' => $v['inage'],
                        'presentTelphone' => $v['presentTelphone'] ?? "",
                        'outhospitalDeptCode' => $v['outList']['deptName'] ?? "",
                        'outhospitalDate' => $v['inList']['outhospitalDate'] ?? "",
                        'diagnosis' => $v['inList']['diagnose'] ?? "",
                        'visit_dept' => $data['visit_dept'],
                        'next_visit_time' => $data['next_visit_time'],
                        'come_visit_time' => '',
                        'status' => 0,
                        'push_type' => $data['push_type'],
                        'push_status' => 0,
                        'period_content' => $data['period_content'],
                        'creator_id' => $data['creator_id'],
                        'creator_dept_name' => $data['creator_dept_name'],
                        'creator_dept_id' => $data['creator_dept_id'],
                        'creator_name' => $data['creator_name'],
                        'created_at' => time(),
                        'updated_at' => time(),
                        'deleted_at' => 0,
                        'push_date' => '',
                        'source' => $data['source'] ?? 'platform',
                        'patientId' => (string)$v["patientId"],
                        'visit_name' => $data["visit_name"] ?? "",
                        'is_stop' => 0,
                        'period' => $data["period"],
                        'remind_count' => $data["remind_count"],
                        'visit_finish_time' => $data['visit_finish_time'] ?? "",
                        'plan_list' => [[
                            'push_status' => 0,
                            'plan_visit_date' => $data['next_visit_time'],
                            'plan_status' => 0,
                            'come_visit_date' => '',
                            'visit_status' => 0]]
                    ];
                }

                $resultPatient = ZhyxMongo::getInstance()->setCollection("visit_plan_detail")->insertMany($arr, ['session' => $session]);
                if ($resultPatient->getInsertedCount() > 0) {
                    //计算推送时间
                    $beforeTime = date("Y-m-d", strtotime("-" . $data['remind_count'] . " day", strtotime($data["next_visit_time"])));
                    //判断如果计算出来的日期比今天日期小了，说明需要走到下一个计划中
                    if ($beforeTime < date("Y-m-d")) {
                        if (!empty($data['period'])) {
                            $beforeTime = date("Y-m-d", strtotime("+" . $weekValue[$data["period"]], strtotime($beforeTime)));
                        } else {
                            $delay = -1;
                        }
                    }

                    $diffDays = date_diff(date_create($beforeTime), date_create(date("Y-m-d")), true);
                    if ($diffDays->days > 0 && $diffDays->invert === 0 && $delay >= 0) {
                        $delay = $diffDays->days;
                    }
                }
                if (isset($data["outer_id"]) && !empty($data["outer_id"])) {
                    (new DiseasePatientTaskDetail())->modifyStatus($data["outer_id"], 2, (string)$result->getInsertedId());
                }

                $session->commitTransaction();
                if ($delay === 0) {
                    $beanstalkdResult = ZhyxBeanstalkd::getInstance()->beansTalk->useTube("sendVisitMessage")->put(json_encode($pushArr, JSON_THROW_ON_ERROR), 0, $delay ?? 0);
                    if (!empty($beanstalkdResult->getId())) {
                        ZhyxMongo::getInstance()->setCollection('visit_plan')->updateOne(["_id" => $result->getInsertedId()], ['$set' => ["queue_id" => $beanstalkdResult->getId()]]);
                    }
                } else {
                    if ($delay !== -1) {
                        //将复诊计划任务投递到任务表中
                        (new TimingTask())->save([
                            'task_name' => '推送复诊计划',
                            'task_status' => 0,
                            'task_plan_date' => date("Y-m-d", strtotime('+' . $delay . ' day')),
                            'task_data' => $pushArr,
                            'deleted_at' => 0,
                            'type' => 'visit_plan'
                        ]);
                    }

                }
                return true;

            }
        } catch (\Exception $exception) {

            if ($session->getTransactionState() !== "none" && $session->getTransactionState() !== "committed") {
                $session->abortTransaction();
            }
            return false;

        }
        return false;
    }

    public function getLists()
    {
        $result = $this->mongoSearch([], ["status", "visit_name", "status", "creator_name"]);
        $uidArr = $this->getUserIds();
        if (!empty($uidArr)) {
            $result = $result->where("creator_id", "in", $uidArr);
        }
        return $result->order("_id", "desc")->paginate($this->pageLimit);

    }

    public function getPushTypeTextAttr($value, $data): string
    {
        $statusTextArr = ["ALL" => "APP/短信", "APP" => "app", "SMS" => "短信"];
        return $statusTextArr[$data["push_type"]];
    }

    public function getStatusTextAttr($value, $data)
    {
        $statusTextArr = [0 => "未推送", 1 => "推送成功", 2 => "推送失败"];
        return $statusTextArr[$data["status"]];
    }

    public function getCanDeleteAttr($value, $data): bool
    {
        //计算推送时间
        $beforeTime = date("Y-m-d", strtotime("-" . $data['remind_count'] . " day", strtotime($data["next_visit_time"])));
        $delay = 0;
        $diffDays = date_diff(date_create($beforeTime), date_create(date("Y-m-d")), false);
        if ($diffDays->days > 0 && $diffDays->invert === 1) {
            return true;
        }
        return false;
    }

    public function getPeriodTextAttr($value, $data): string
    {

        $weekValue = ["1" => "一周", "2" => "半个月", "3" => "一个月", "4" => "一季度", "5" => "半年", "6" => "年"];
        return $weekValue[$data["period"]] ?? "无";
    }


}